<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/9/9
 * Time: 23:07
 */

namespace app\index\controller;

use think\Controller;

class Decode extends Controller
{

    public function index()
    {
        $CommonVar = [
            '$_SERVER' => [],
            '$_GET' => [],
            '$GLOBALS' => [],
        ];

        foreach ($GLOBALS as $key => $value) {
            $encode = mb_detect_encoding($key, array("ASCII"));

            if ($encode !== 'ASCII') {
                //$CommonVar['$GLOBALS'][$key] = $value;
            }
        }
        foreach ($_GET as $key => $value) {
            $encode = mb_detect_encoding($key, array("ASCII"));

            if ($encode !== 'ASCII') {
                //$CommonVar['$_GET'][$key] = $value;
            }
        }
        foreach ($_SERVER as $key => $value) {
            $encode = mb_detect_encoding($key, array("ASCII"));

            if ($encode !== 'ASCII') {
                //$CommonVar['$_SERVER'][$key] = $value;
            }
        }


        //halt(get_defined_constants());
        header('Content-type:text/html;Charset=utf-8');

        $filePath = 'application/common/controller/Admin.php';


        $output = file_get_contents($filePath);


        //dump($output);
        $allVar = [];
        $ErrString = [];
        getphpCode($output, $allVar, $ErrString);


        $pat_array = [];

        $this->replace_all_isset_global($output, $CommonVar);

        //最后的文本将$this->request->{'param'}类似的转化
        $pattner = '/\{\'([a-zA-Z_]*?)\'\}/';
        preg_match_all($pattner, $output, $pat_array);

        foreach ($pat_array[0] as $key => $value) {
            $output = str_replace($value, $pat_array[1][$key], $output);
        }

        //将最后的文本  defind(xx,xxx); 删掉
        $pattner = '/define\([\s\S]*?\)\;/';
        preg_match_all($pattner, $output, $pat_array);

        foreach ($pat_array[0] as $key => $value) {
            $output = str_replace($value, '', $output);
        }

        //将最后的文本中 return $this->success(    ->   $this->success(
        //将最后的文本中 return $this->error(    ->   $this->error(
        $output = str_replace('return $this->success(', '$this->success(', $output);
        $output = str_replace('return $this->error(', '$this->error(', $output);

        dump($pat_array);
        dump($CommonVar);
        dump($output);
        put_stop($output);
        die;

    }


    /** info:替换所有的已经定义的变量
     * @param $output
     * @param $CommonVar
     */
    public function replace_all_isset_global(&$output,&$CommonVar){
        //先匹配是否有$Ser[xxx] = explode(xxx)格式的，将如$CommonVar
        //匹配是否有explode的数据
        $pattern = '/(\$_SERVER|\$_GET|\$GLOBALS)(\{(.*?)\}|\[(.*?)\])[\s]?\=[\s]?explode\(\'(.*?)\',[\s]*([\s\S]*?)\)\;/';

        $result = preg_match($pattern, $output, $pat_array);

        if($result){
            //explode\('([\s\S]*?)',[\s]*(gzinflate\(substr\('([\s\S]*?)',[\s\S]*?,[\s\S]*?\)\))\)\;
            $pattern = '/(\$_SERVER|\$_GET|\$GLOBALS)(\{(.*?)\}|\[(.*?)\])[\s]?\=[\s]?(explode\(\'(.*?)\',[\s]?(gzinflate\(substr\(\'([\s\S]*?)\',[\s\S]*?,[\s\S]*?\)\))\))\;/';

            $result = preg_match($pattern, $output, $pat_array_li);

            if($result){
                //匹配gzinflate 需要解压缩
                $pat_array = $pat_array_li;
                $explode_result = return_explode($pat_array[5]);

                if(empty($explode_result[0])){
                    $explode_result = explode($pat_array[6],gzinflate_decode($pat_array[8]));
                    if(empty($explode_result[0])){
                        getphpCode($output, $allVar, $gzinflateStr);
                        dump('错误!');
                        halt($gzinflateStr);
                    }
                }
                dump('解析出数组');
                dump($explode_result);
                $variable_name = $pat_array[1];
                if(!empty($pat_array[3])){
                    $key_name = $pat_array[3];
                }else{
                    $key_name = $pat_array[4];
                }
                $CommonVar[$variable_name][$key_name] = $explode_result;

                $str = PHP_EOL . $variable_name . '[' . $key_name . '] = ' . array_format_echo($explode_result) . ';' . PHP_EOL;
                //如果匹配上了的话，将字符串格式话成数组拼接转化
                $output = str_replace($pat_array[0], $str, $output);
                $this->replace_all_global_variable($output,$CommonVar);
                //put_stop($output);
                //转换之后  删除第一次匹配
                $output = str_replace($str, PHP_EOL, $output);

            }else{
                ob_clean();
                //没有匹配到需要gzinflate解码的数据
                //不需要解压缩，直接获得explode之后的数据
                //$pattern = '/(\$_SERVER|\$_GET|\$GLOBALS)(\{([\s\S]*?)\}|\[([\s\S]*?)\])[\s]?\=[\s]?explode\(\'([\s\S]*?)\',[\s]?\'(.*?)\'\)\;/';
                //注意: 由于正则表达式中 . 表示出换行符以外的所有单个字符，所以需要用到[\s\S]
                $pattern = '/(\$_SERVER|\$_GET|\$GLOBALS)(\{(.*?)\}|\[(.*?)\])[\s]?\=[\s]?explode\(\'(.*?)\',[\s]?\'([\s\S]*?)\'\)\;/';
                $result = preg_match($pattern, $output, $pat_array);
                dump('66');

                if($result){
                    $variable_name = $pat_array[1];
                    //如果匹配到第三个、第四个有一个OK
                    if(!empty($pat_array[3])){
                        $key_name = $pat_array[3];
                    }else{
                        $key_name = $pat_array[4];
                    }
                    //explode爆裂后的数据
                    $explode_result = explode($pat_array[5],stripcslashes($pat_array[6]));
                    if(count($explode_result)>1){
                        //加入全局数组
                        $CommonVar[$variable_name][$key_name] = $explode_result;
                    }else{
                        $explode_result = explode($pat_array[5],$pat_array[6]);
                        //加入全局数组
                        $CommonVar[$variable_name][$key_name] = $explode_result;
                    }

                    //将匹配到的explode格式话成数组格式
                    $str = PHP_EOL . $variable_name . '[' . $key_name . '] = ' . array_format_echo($explode_result) . ';' . PHP_EOL;
                    $output = str_replace($pat_array[0], $str, $output);

                    //替换所有变量
                    $this->replace_all_global_variable($output,$CommonVar);

                    //转换之后  删除第一次匹配
                    $output = str_replace($str, PHP_EOL, $output);
                }
            }
            dump($output);
            //替换文中引用全局变量的变量
            $this->replace_yinyong_variables($output,$CommonVar);
            dump($CommonVar);

            //持续替换已定义的变量
            $this->replace_all_isset_global($output,$CommonVar);

        } else{

            //ob_clean();
            //halt($CommonVar);
            //替换文中引用全局变量的变量
            //$this->replace_yinyong_variables($output,$CommonVar);
            //替换所有变量
            $this->replace_all_global_variable($output,$CommonVar);

        }
    }


    //替换所有的全局变量
    public function replace_all_global_variable(&$output,&$CommonVar){
        $End = 0;
        foreach($CommonVar as $variable_name=>$variable_value){
            $break = 0;
            foreach($variable_value as $key=>$value){
                $explode_result = $CommonVar[$variable_name][$key];
                dump($variable_name);
                dump($key);
                $key = trim($key,'\'');
                //四种   $variable_name[$value]
                //四种   $variable_name['\''.$value.'\'']
                //四种   $variable_name{$value}
                //四种   $variable_name{'\''.$value.'\''}
                $i=0;

                $pattern[1] = '/'.preg_quote($variable_name.'['.$key.']').'(\{([^\{^\[]*?)\}|\[([^\[^\{]*?)\])/';
                $pattern[2] = '/'.preg_quote($variable_name.'[\''.$key.'\']').'(\{([^\{^\[]*?)\}|\[([^\[^\{]*?)\])/';
                $pattern[3] = '/'.preg_quote($variable_name.'{'.$key.'}').'(\{([^\{^\[]*?)\}|\[([^\[^\{]*?)\])/';
                $pattern[4] = '/'.preg_quote($variable_name.'{\''.$key.'\'}').'(\{([^\{^\[]*?)\}|\[([^\[^\{]*?)\])/';
                foreach($pattern as $k=>$v){
                    preg_match_all($v,$output,$pat_array);
                    dump($pat_array);
                    if(count($pat_array[0])>0){
                        $this->replace_global_variable($output,$pat_array,$explode_result);
                    }else{
                        $i++;
                    }
                }
                if($i==4){
                    //如果四种模式都没有匹配，父级foreach跳出
                    $break=1;
                    continue;
                }
            }
            if($break==1){
                $End = 1;
                continue;
            }
        }
        if($End !== 1){
            $this->replace_all_global_variable($output,$CommonVar);
        }
    }

    public function replace_global_variable(&$output, $pat_array, $explode_result)
    {

        foreach ($pat_array[0] as $key => $value) {
            $index = $pat_array[2][$key];
            if ($index !== '') {
                //dump($index);
                if (isset($explode_result[$index])) {

                    $relace_str = $explode_result[$index];
                    //dump('有-'.$relace_str);
                    if (!function_exists($relace_str)) {
                        $relace_str = array_format_echo($relace_str);
                    }
                    //dump($value);dump('=>');dump($relace_str);
                    $output = str_replace($value, $relace_str, $output);
                }else{
                    //dump('没有');
                }
            }
        }

        //一个是字符串
        foreach ($pat_array[0] as $key => $value) {
            $index = $pat_array[3][$key];
            if ($index !== '') {
                if (isset($explode_result[$index])) {
                    $relace_str = $explode_result[$index];
                    //dump('有-'.$relace_str);
                    if (!function_exists($relace_str)) {
                        $relace_str = array_format_echo($relace_str);
                    }
                    //dump($value);dump('=>');dump($relace_str);
                    $output = str_replace($value, $relace_str, $output);
                }else{
                    //dump('没有');
                }
            }
        }
    }

    /** 匹配到 $var_xx = &$Goll[xx];
     * @param $output
     * @param $CommonVar
     */
    public function replace_yinyong_variables(&$output,&$CommonVar){

        $pattern = '/(\$var_[0-9]*?)+[\s]?\=[\s]?[\&]?[\s]?((\$_SERVER|\$_GET|\$GLOBALS)(\{([^\[^\{]+?)\}|\[([^\[^\{]+?)\]+?))\;/';
        preg_match_all($pattern, $output, $pat_array);
        //匹配所有经引用的变量
        dump('匹配所有经引用的变量');
        dump($pat_array);
        if (count($pat_array[0])>0) {
            foreach ($pat_array[5] as $key => $value) {
                $replcae_var = $pat_array[1][$key];
                $variable_name = $pat_array[3][$key];
                $key_name = $value;
                if(isset($CommonVar[$variable_name][$key_name])){
                    $decode_result = $CommonVar[$variable_name][$key_name];
                }else{
                    $decode_result = $CommonVar[$variable_name]['\''.$key_name.'\''];
                }
                $CommonVar[$replcae_var] = $CommonVar[$variable_name];

                if(!empty($decode_result)){
                    $pattern = '/' . preg_quote($replcae_var) . '(\{([^\[]+?)\}|\[([^\}]+?)\]+?)/';
                    preg_match_all($pattern, $output, $pat_array_li);
                    $this->replace_global_variable($output,$pat_array_li,$decode_result);
                    //清除无效的
                    $output = str_replace($pat_array[0][$key], PHP_EOL, $output);
                }

            }
            //开始替换:  方法里面重新定义变量，引用了全局变量
        }

    }

}


